package com.api.predict.controller;

import com.api.core.annotation.PowerEnable;
import com.api.core.controller.Ctrl;
import com.api.core.response.Result;
import com.api.core.response.ResultCode;
import com.api.core.response.ResultGenerator;
import com.api.predict.condition.OrderCondition;
import com.api.predict.form.CreatePredictForm;
import com.api.predict.model.Predict;
import com.api.predict.service.PredictService;
import com.api.predict.vo.PredictRegistrationVo;
import com.api.predict.vo.PredictResultVo;
import com.api.predict.vo.PredictTeamVo;
import com.api.predict.vo.PredictVo;
import com.api.user.exception.CoinChangedException;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author RenQiang
 * @date 2021/6/5
 */
@PowerEnable(name = "竞猜", url = "/predict")
@Api(value = "竞猜", tags = {PredictController.API_TAG})
@RestController
@RequestMapping("/predict")
@Validated
public class PredictController extends Ctrl {
    public static final String API_TAG = "竞猜";

    private final PredictService predictService;

    public PredictController(PredictService predictService) {
        this.predictService = predictService;
    }

    @ApiOperation(value = "创建竞猜", tags = {API_TAG}, notes = "创建竞猜")
    @PostMapping("/create")
    public Result create(@Valid @RequestBody CreatePredictForm form) {
        try {
            predictService.createNewPredict(form);
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
        return ResultGenerator.genCreatedSuccessResult();
    }

    @ApiOperation(value = "修改竞猜", tags = {API_TAG}, notes = "修改竞猜")
    @PostMapping("/update")
    public Result update(@Valid @RequestBody CreatePredictForm form) {
        try {
            predictService.updatePredict(form);
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
        return ResultGenerator.genCreatedSuccessResult();
    }

    @ApiOperation(value = "删除竞猜", tags = {API_TAG}, notes = "删除竞猜")
    @PostMapping("/delete")
    public Result delete(@RequestParam Long predictId) {
        try {
            predictService.deletePredict(predictId);
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
        return ResultGenerator.genCreatedSuccessResult();
    }

    @ApiOperation(value = "分页查询竞猜列表", tags = {API_TAG}, notes = "分页查询竞猜列表")
    @GetMapping("/list-by-page")
    public Result listByPage(Authentication authentication,
                             @ApiParam(value = "排序方式") @RequestParam OrderCondition order,
                             @ApiParam(value = "搜索关键字") @RequestParam(required = false) String keyword,
                             @ApiParam(value = "是否置顶") @RequestParam(required = false) Boolean top,
                             @ApiParam(value = "游戏ID") @RequestParam(required = false) Long gameId,
                             @ApiParam(value = "页号") @RequestParam(defaultValue = "1") Integer page,
                             @ApiParam(value = "分页大小") @RequestParam(defaultValue = "10") Integer size,
                             @ApiParam(value = "是否只查询当前用户参与过的竞猜") @RequestParam(defaultValue = "false") Boolean currentUserOnly,
                             @ApiParam(value = "是否已完成") @RequestParam(required = false) Boolean completed) {
        Map<String, String> orderParams = new HashMap<>(4);
        if (order == OrderCondition.NEW_TO_OLD) {
            orderParams.put("start_time", "desc");
        } else if (order == OrderCondition.OLD_TO_NEW) {
            orderParams.put("start_time", "asc");
        }
        Map<String, Object> queryParams = new HashMap<>(4);
        if (StringUtils.isNotEmpty(keyword)) {
            queryParams.put("keyword", keyword);
        }
        if (top != null) {
            queryParams.put("top", top);
        }
        if (gameId != null) {
            queryParams.put("gameId", gameId);
        }
        if (currentUserOnly != null && currentUserOnly) {
            queryParams.put("userId", getAuthUser(authentication).getId());
        }
        if (completed != null) {
            queryParams.put("completed", completed);
        }
        PageInfo<PredictVo> pageInfo = predictService.listByPage(queryParams, orderParams, page, size);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @ApiOperation(value = "获取竞猜战队列表", tags = {API_TAG}, notes = "获取竞猜战队列表")
    @GetMapping("/get-teams")
    public Result getPredictTeams(@ApiParam(name = "竞猜ID") @RequestParam Long predictId) {
        List<PredictTeamVo> predictTeams = predictService.getPredictTeams(predictId);
        return ResultGenerator.genSuccessResult(predictTeams);
    }

    @ApiOperation(value = "获取竞猜参与者列表", tags = {API_TAG}, notes = "获取竞猜参与者列表")
    @GetMapping("/get-registrations")
    public Result getPredictRegistrations(@ApiParam(name = "竞猜ID") @RequestParam Long predictId) {
        List<PredictRegistrationVo> predictRegistrations = predictService.getPredictRegistrations(predictId);
        return ResultGenerator.genSuccessResult(predictRegistrations);
    }

    @ApiOperation(value = "竞猜下注", tags = {API_TAG}, notes = "竞猜下注")
    @PostMapping("/registry")
    public Result registry(Authentication authentication,
                               @ApiParam(name = "竞猜ID") @RequestParam Long predictId,
                               @ApiParam(name = "预测结果（战队ID列表）") @RequestParam @NotEmpty List<Long> predictTeamIds) throws CoinChangedException {
        Long userId = getAuthUser(authentication).getId();
        try {
            try {
                predictService.registry(userId, predictId, predictTeamIds);
            } catch (CoinChangedException ignore) {
                predictService.registry(userId, predictId, predictTeamIds);
            }
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
        return ResultGenerator.genCreatedSuccessResult();
    }

    @ApiOperation(value = "添加置顶海报", tags = {API_TAG}, notes = "添加置顶海报")
    @PostMapping("/add-carousel")
    public Result addCarousel(@ApiParam(name = "竞猜ID") @RequestParam Long predictId,
                              @ApiParam(name = "置顶海报（轮播图）") @RequestParam String carousel) {
        Predict predict = predictService.findById(predictId);
        if (predict == null) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), "Predict and win not exist");
        }
        predict.setCarousel(carousel);
        predictService.save(predict);
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "结束竞猜", tags = {API_TAG}, notes = "结束竞猜")
    @PostMapping("/complete")
    public Result complete(@ApiParam(name = "竞猜ID") @RequestParam Long predictId,
                           @ApiParam(name = "胜利组战队ID列表") @RequestParam @NotEmpty List<Long> victoryTeamIds) throws CoinChangedException {
        try {
            try {
                predictService.complete(predictId, victoryTeamIds);
            } catch (CoinChangedException ignore) {
                predictService.complete(predictId, victoryTeamIds);
            }
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
        return ResultGenerator.genSuccessResult();
    }

    @ApiOperation(value = "获取竞猜结果", tags = {API_TAG}, notes = "获取竞猜结果")
    @GetMapping("/get-result")
    public Result getPredictResult(Authentication authentication,
                                   @ApiParam(name = "竞猜ID") @RequestParam Long predictId) {
        try {
            Long userId = getAuthUser(authentication).getId();
            PredictResultVo predictResultVo = predictService.getPredictResult(predictId, userId);
            return ResultGenerator.genSuccessResult(predictResultVo);
        } catch (IllegalArgumentException e) {
            return ResultGenerator.genFailResult(ResultCode.FAIL.code(), e.getMessage());
        }
    }
}
